<template>
  <div class="code-block" :class="{ 'theme-dark': currentTheme === 'dark', 'theme-light': currentTheme === 'light' }">
    <div class="code-header">
      <div class="code-info">
        <span class="language-icon">{{ getLanguageIcon() }}</span>
        <span class="language-name">{{ getLanguageName() }}</span>
      </div>
      <div class="code-actions">
        <button 
          class="theme-toggle" 
          @click="toggleTheme"
          title="切换主题"
        >
          {{ currentTheme === 'dark' ? '🌙' : '☀️' }}
        </button>
        <CopyButton
          v-if="copyEnabled"
          :content="code"
          label="复制"
          successLabel="已复制!"
          title="复制代码到剪贴板"
          @copy-success="handleCopySuccess"
        />
      </div>
    </div>
    
    <div class="code-container" :style="{ maxHeight }">
      <div v-if="language === 'markdown'" v-html="highlightedCode"></div>
      <div v-else class="code-content" v-html="highlightedCode"></div>
    </div>
  </div>
</template>

<script setup>
/**
 * 代码块显示组件
 * 支持语法高亮和复制功能
 */
import { ref, onMounted, watch } from 'vue'
import { marked } from 'marked'
import Prism from 'prismjs'
import 'prismjs/themes/prism-tomorrow.min.css'
import 'prismjs/components/prism-typescript'
import 'prismjs/components/prism-sql'
import 'prismjs/components/prism-json'
import 'prismjs/components/prism-bash'
import 'prismjs/components/prism-markdown'
import 'prismjs/plugins/line-numbers/prism-line-numbers'
import 'prismjs/plugins/line-numbers/prism-line-numbers.css'
import CopyButton from './CopyButton.vue'

const props = defineProps({
  /**
   * 代码内容
   */
  code: {
    type: String,
    required: true
  },
  
  /**
   * 代码语言
   */
  language: {
    type: String,
    default: 'typescript'
  },
  
  /**
   * 是否显示行号
   */
  showLineNumbers: {
    type: Boolean,
    default: true
  },
  
  /**
   * 是否启用复制功能
   */
  copyEnabled: {
    type: Boolean,
    default: true
  },
  
  /**
   * 默认主题 (light or dark)
   */
  theme: {
    type: String,
    default: 'dark'
  },
  
  /**
   * 标签标题
   */
  label: {
    type: String,
    default: ''
  },
  
  /**
   * 最大高度
   */
  maxHeight: {
    type: String,
    default: 'none'
  }
})

// 高亮后的代码HTML
const highlightedCode = ref('')
// 是否已复制
const isCopied = ref(false)
// 当前主题
const currentTheme = ref(props.theme)

// 支持的语言图标
const languageIcons = {
  typescript: '📘',
  javascript: '📙',
  html: '📄',
  css: '🎨',
  json: '📋',
  sql: '💾',
  bash: '💻',
  markdown: '📝',
  default: '📃'
}

// 语言显示名称
const languageNames = {
  typescript: 'TypeScript',
  javascript: 'JavaScript',
  html: 'HTML',
  css: 'CSS',
  json: 'JSON',
  sql: 'SQL',
  bash: 'Shell',
  markdown: 'Markdown',
  default: 'Code'
}

// 获取语言图标
const getLanguageIcon = () => {
  return languageIcons[props.language] || languageIcons.default
}

// 获取语言显示名称
const getLanguageName = () => {
  return props.label || languageNames[props.language] || languageNames.default
}

// 高亮代码
const highlightCode = () => {
  if (!props.code) {
    highlightedCode.value = ''
    return
  }
  
  try {
    // 处理Markdown
    if (props.language === 'markdown') {
      // 使用marked将markdown转换为HTML
      const htmlContent = marked(props.code)
      highlightedCode.value = `<div class="markdown-content">${htmlContent}</div>`
      return
    }
    
    // 其他语言使用Prism高亮
    const language = Prism.languages[props.language] || Prism.languages.plain
    const highlighted = Prism.highlight(props.code, language, props.language)
    
    // 添加行号
    if (props.showLineNumbers) {
      const lines = highlighted.split('\n')
      const numberedLines = lines.map((line, index) => {
        return `<span class="line-number">${index + 1}</span><span class="line-content">${line}</span>`
      }).join('\n')
      
      highlightedCode.value = `<pre class="line-numbers"><code class="language-${props.language}">${numberedLines}</code></pre>`
    } else {
      highlightedCode.value = `<pre><code class="language-${props.language}">${highlighted}</code></pre>`
    }
  } catch (err) {
    console.error('代码高亮错误:', err)
    // 出错时显示原始代码
    highlightedCode.value = `<pre><code>${props.code}</code></pre>`
  }
}

// 复制成功回调
const handleCopySuccess = () => {
  isCopied.value = true
  setTimeout(() => {
    isCopied.value = false
  }, 2000)
}

// 切换主题
const toggleTheme = () => {
  currentTheme.value = currentTheme.value === 'dark' ? 'light' : 'dark'
}

// 监听代码变化
watch(() => props.code, () => {
  highlightCode()
}, { immediate: true })

// 组件挂载后初始化
onMounted(() => {
  highlightCode()
})
</script>

<style scoped>
.code-block {
  border-radius: 8px;
  overflow: hidden;
  margin: 0;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.theme-dark {
  --code-bg: #1e1e1e;
  --header-bg: #2d2d2d;
  --border-color: #444;
  --text-color: #eee;
  --accent-color: #569cd6;
  --comment-color: #6a9955;
  --string-color: #ce9178;
  --keyword-color: #c586c0;
  --type-color: #4ec9b0;
}

.theme-light {
  --code-bg: #f8f8f8;
  --header-bg: #e8e8e8;
  --border-color: #ddd;
  --text-color: #333;
  --accent-color: #0074c1;
  --comment-color: #008000;
  --string-color: #a31515;
  --keyword-color: #af00db;
  --type-color: #2b91af;
}

.code-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  background-color: var(--header-bg);
  border-bottom: 1px solid var(--border-color);
}

.code-info {
  display: flex;
  align-items: center;
  color: var(--text-color);
}

.language-icon {
  margin-right: 8px;
  font-size: 1.2rem;
}

.language-name {
  font-size: 0.9rem;
  font-weight: 500;
}

.code-actions {
  display: flex;
  gap: 8px;
}

.theme-toggle {
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px 8px;
  font-size: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  color: var(--text-color);
  opacity: 0.7;
  transition: all 0.2s;
}

.theme-toggle:hover {
  opacity: 1;
  background-color: rgba(128, 128, 128, 0.2);
}

.code-container {
  background-color: var(--code-bg);
  overflow: auto;
  position: relative;
}

.code-content {
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
  font-size: 0.9rem;
  line-height: 1.5;
  overflow-x: auto;
  padding: 1rem;
  white-space: pre;
}

/* 增强高亮效果 */
:deep(.token.comment),
:deep(.token.prolog),
:deep(.token.doctype),
:deep(.token.cdata) {
  color: var(--comment-color);
  font-style: italic;
}

:deep(.token.punctuation) {
  color: var(--text-color);
}

:deep(.token.property),
:deep(.token.tag),
:deep(.token.boolean),
:deep(.token.number),
:deep(.token.constant),
:deep(.token.symbol) {
  color: var(--accent-color);
}

:deep(.token.selector),
:deep(.token.string),
:deep(.token.char),
:deep(.token.builtin) {
  color: var(--string-color);
}

:deep(.token.operator),
:deep(.token.entity),
:deep(.token.url),
:deep(.language-css .token.string),
:deep(.style .token.string) {
  color: #bbb;
}

:deep(.token.atrule),
:deep(.token.attr-value),
:deep(.token.keyword) {
  color: var(--keyword-color);
  font-weight: 500;
}

:deep(.token.function),
:deep(.token.class-name),
:deep(.token.important) {
  color: var(--type-color);
}

:deep(.token.regex),
:deep(.token.variable) {
  color: #e90;
}

/* 自定义滚动条 */
.code-container::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.code-container::-webkit-scrollbar-track {
  background: var(--code-bg);
}

.code-container::-webkit-scrollbar-thumb {
  background-color: var(--border-color);
  border-radius: 4px;
}

.code-container::-webkit-scrollbar-thumb:hover {
  background-color: #666;
}

/* Markdown内容样式 */
:deep(.markdown-content) {
  padding: 16px;
  color: var(--text-color);
  line-height: 1.6;
}

:deep(.markdown-content h1),
:deep(.markdown-content h2),
:deep(.markdown-content h3),
:deep(.markdown-content h4),
:deep(.markdown-content h5),
:deep(.markdown-content h6) {
  margin-top: 1.5em;
  margin-bottom: 0.75em;
  font-weight: 600;
}

:deep(.markdown-content h1) {
  font-size: 1.8em;
  padding-bottom: 0.3em;
  border-bottom: 1px solid var(--border-color);
}

:deep(.markdown-content h2) {
  font-size: 1.5em;
  padding-bottom: 0.3em;
  border-bottom: 1px solid var(--border-color);
}

:deep(.markdown-content p) {
  margin: 0.8em 0;
}

:deep(.markdown-content a) {
  color: var(--accent-color);
  text-decoration: none;
}

:deep(.markdown-content a:hover) {
  text-decoration: underline;
}

:deep(.markdown-content table) {
  border-collapse: collapse;
  width: 100%;
  margin: 1em 0;
}

:deep(.markdown-content table th),
:deep(.markdown-content table td) {
  border: 1px solid var(--border-color);
  padding: 8px 12px;
  text-align: left;
}

:deep(.markdown-content table th) {
  background-color: rgba(0, 0, 0, 0.1);
  font-weight: 600;
}

:deep(.markdown-content code) {
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
  padding: 0.2em 0.4em;
  margin: 0;
  font-size: 0.85em;
  background-color: rgba(128, 128, 128, 0.2);
  border-radius: 3px;
}

:deep(.markdown-content pre code) {
  padding: 0;
  background-color: transparent;
}

:deep(.markdown-content blockquote) {
  margin: 1em 0;
  padding: 0 1em;
  color: var(--text-color);
  border-left: 0.25em solid var(--border-color);
}

:deep(.markdown-content ul),
:deep(.markdown-content ol) {
  padding-left: 2em;
  margin: 0.8em 0;
}

:deep(.line-numbers) .line-number {
  display: inline-block;
  width: 2.5em;
  padding-right: 0.5em;
  text-align: right;
  color: #666;
  user-select: none;
  margin-right: 0.5em;
  border-right: 1px solid var(--border-color);
}

:deep(.line-numbers) .line-content {
  display: inline;
}

/* 针对Typescript特殊强调 */
:deep(.language-typescript) .token.decorator {
  color: #bd63c5;
}

:deep(.language-typescript) .token.namespace {
  color: #4ec9b0;
  font-style: italic;
}

:deep(.language-typescript) .token.interface,
:deep(.language-typescript) .token.type {
  color: #4ec9b0;
}

:deep(.language-typescript) .token.parameter {
  color: #9cdcfe;
}

/* 针对行高亮效果 */
:deep(.highlighted-line) {
  background-color: rgba(255, 255, 0, 0.1);
  display: block;
  margin: 0 -1rem;
  padding: 0 1rem;
}
</style> 